
/*
 * Copyright (C) 2009 Archie L. Cobbs. All rights reserved.
 *
 * $Id: XMLCollectionField.java 377 2010-03-11 20:50:18Z archie.cobbs $
 */

package org.dellroad.sidekar.xml;

import java.util.Collection;
import java.util.Iterator;

import org.dellroad.sidekar.CollectionField;
import org.dellroad.sidekar.Item;
import org.dellroad.sidekar.SimpleField;

/**
 * Container for a {@link CollectionField}'s value during the Sidekar XML import/export process.
 */
abstract class XMLCollectionField<E> extends XMLField {

    private Collection<E> collection;
    private SimpleField<E> elementField;

    // Used during unmarshalling
    protected XMLCollectionField(XMLItem xmlItem) {
        super(xmlItem);
    }

    // Used during marshalling
    protected XMLCollectionField(Item<?> item, CollectionField<E> field) {
        super(field.getName());
        this.collection = field.get(item);
        this.elementField = field.getElementField();
    }

    // Used during marshalling
    @Override
    public boolean hasDefaultValue() {
        return this.collection.isEmpty();
    }

    // Used during unmarshalling
    @Override
    protected SimpleField<?> getNestedField() {
        getCollection();
        return this.elementField;
    }

    // Used during unmarshalling
    public void add(XMLSimpleField xmlField) {
        getCollection();
        this.collection.add(this.elementField.cast(xmlField.getObjectValue()));
    }

    // Used during unmarshalling
    @SuppressWarnings("unchecked")
    private Collection<E> getCollection() {
        if (this.collection == null) {
            CollectionField<E> field = (CollectionField<E>)getField();
            this.collection = field.get(getItem());
            this.elementField = field.getElementField();
        }
        return this.collection;
    }

    // Used during unmarshalling
    public Iterator<XMLSimpleField> iterator() {
        return new SimpleDatabaseIterator<XMLSimpleField, E>(this.collection.iterator()) {

            @Override
            protected XMLSimpleField getNext() {
                XMLSimpleFieldSwitch fieldSwitch = new XMLSimpleFieldSwitch(this.i.next());
                elementField.visit(fieldSwitch);
                return fieldSwitch.getXMLSimpleField();
            }
        };
    }

    @Override
    protected <E> void caseCollectionField(CollectionField<E> field) {
        // do nothing
    }
}
